﻿using ScottPlot;
using ScottPlot.Plottables;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Log;
using UtilZ.Dotnet.Ex.Model;

namespace WinFormApp
{
    public partial class FTestDownSample : Form
    {
        public FTestDownSample()
        {
            InitializeComponent();
        }


        private void FTestDownSampleHelper_Load(object sender, EventArgs e)
        {
            try
            {
                this.InitLog();

                InitControl();

                Loger.Info("已就绪.");
            }
            catch (Exception ex)
            {
                Loger.Error(ex);
            }
        }

        private void InitLog()
        {
            var redirectAppenderToUI = (RedirectAppender)Loger.GetAppenderByName(null, "RedirectToUI");
            if (redirectAppenderToUI != null)
            {
                redirectAppenderToUI.RedirectOuput += RedirectLogOutput;
            }

            checkBoxLockLog.Checked = logControl.IsLock;
            checkBoxLockLog.CheckedChanged += CheckBoxLockLog_CheckedChanged;
        }

        private void CheckBoxLockLog_CheckedChanged(object sender, EventArgs e)
        {
            logControl.IsLock = checkBoxLockLog.Checked;
        }

        private void RedirectLogOutput(object sender, RedirectOuputArgs e)
        {
            logControl.AddLog(e.Item.Content, e.Item.Level);
        }

        private void btnClearLog_Click(object sender, EventArgs e)
        {
            logControl.Clear();
        }

        private void FTestDownSampleHelper_FormClosing(object sender, FormClosingEventArgs e)
        {
            this._inputDataPointer.Dispose();
            this._outputDataPointer.Dispose();
        }



        private readonly UnmanagedMemoryPointer<double> _inputDataPointer = new UnmanagedMemoryPointer<double>();
        private readonly UnmanagedMemoryPointer<double> _outputDataPointer = new UnmanagedMemoryPointer<double>();
        private Crosshair _crosshairSrc = null;
        private Crosshair _crosshairRet = null;

        private void InitControl()
        {

            formsPlotSrc.SKControl.MouseEnter += SKControl_MouseEnter;
            formsPlotSrc.SKControl.MouseLeave += SKControl_MouseLeave;
            formsPlotSrc.MouseMove += FormsPlotSrc_MouseMove;

            formsPlotRet.SKControl.MouseEnter += SKControl_MouseEnter;
            formsPlotRet.SKControl.MouseLeave += SKControl_MouseLeave;
            formsPlotRet.MouseMove += FormsPlotSrc_MouseMove;
        }

        private void AddCrosshair()
        {
            this._crosshairSrc = formsPlotSrc.Plot.Add.Crosshair(0, 0);
            this._crosshairSrc.TextColor = ScottPlot.Colors.Red;
            this._crosshairSrc.TextBackgroundColor = ScottPlot.Colors.Green;
            this._crosshairSrc.IsVisible = true;

            this._crosshairRet = formsPlotRet.Plot.Add.Crosshair(0, 0);
            this._crosshairRet.TextColor = ScottPlot.Colors.Red;
            this._crosshairRet.TextBackgroundColor = ScottPlot.Colors.Green;
            this._crosshairRet.IsVisible = true;
        }

        private void FormsPlotSrc_MouseMove(object sender, MouseEventArgs e)
        {
            if (sender == formsPlotSrc)
            {
                if (this._crosshairSrc != null)
                {
                    var mousePixel = new ScottPlot.Pixel(e.X, e.Y);
                    ScottPlot.Coordinates mouseCoordinates = formsPlotSrc.Plot.GetCoordinates(mousePixel);
                    this.Text = $"X={mouseCoordinates.X:N3}, Y={mouseCoordinates.Y:N3}";
                    this._crosshairSrc.Position = mouseCoordinates;
                    this._crosshairSrc.VerticalLine.Text = $"{mouseCoordinates.X:N3}";
                    this._crosshairSrc.HorizontalLine.Text = $"{mouseCoordinates.Y:N3}";
                    formsPlotSrc.Refresh();
                }
            }
            else
            {
                if (this._crosshairRet != null)
                {
                    var mousePixel = new ScottPlot.Pixel(e.X, e.Y);
                    ScottPlot.Coordinates mouseCoordinates = formsPlotRet.Plot.GetCoordinates(mousePixel);
                    this.Text = $"X={mouseCoordinates.X:N3}, Y={mouseCoordinates.Y:N3}";
                    this._crosshairRet.Position = mouseCoordinates;
                    this._crosshairRet.VerticalLine.Text = $"{mouseCoordinates.X:N3}";
                    this._crosshairRet.HorizontalLine.Text = $"{mouseCoordinates.Y:N3}";
                    formsPlotRet.Refresh();
                }
            }

        }

        private void SKControl_MouseLeave(object sender, EventArgs e)
        {
            if (sender == formsPlotSrc)
            {
                if (this._crosshairSrc != null)
                {
                    formsPlotSrc.Refresh();
                    this._crosshairSrc.IsVisible = false;
                }
            }
            else
            {
                if (this._crosshairRet != null)
                {
                    this._crosshairRet.IsVisible = false;
                    formsPlotRet.Refresh();
                }
            }

            Loger.Info("MouseLeave");
        }

        private void SKControl_MouseEnter(object sender, EventArgs e)
        {
            if (sender == formsPlotSrc)
            {
                if (this._crosshairSrc != null)
                {
                    formsPlotSrc.Refresh();
                    this._crosshairSrc.IsVisible = true;
                }
            }
            else
            {
                if (this._crosshairRet != null)
                {
                    this._crosshairRet.IsVisible = true;
                    formsPlotRet.Refresh();
                }
            }

            Loger.Info("MouseEnter");
        }

        private void ShowData(double[] inputData, double[] outputData)
        {
            formsPlotSrc.Plot.Clear();
            formsPlotSrc.Plot.Add.Signal(inputData);

            formsPlotRet.Plot.Clear();
            formsPlotRet.Plot.Add.Signal(outputData);

            this.AddCrosshair();

            formsPlotSrc.Plot.Axes.Margins();
            formsPlotSrc.Plot.Axes.AutoScale();
            formsPlotSrc.Plot.Font.Automatic();
            formsPlotSrc.Refresh();

            formsPlotRet.Plot.Axes.Margins();
            formsPlotRet.Plot.Axes.AutoScale();
            formsPlotRet.Plot.Font.Automatic();
            formsPlotRet.Refresh();


        }


        private double[] _inputData = new double[1000];
        private double[] _outputData = new double[100];
        private readonly Random _rnd = new Random(Environment.TickCount);
        private void btnInit_Click(object sender, EventArgs e)
        {
            this._inputData = new double[(int)numInputDataLength.Value];
            this._outputData = new double[(int)numOutputDataLength.Value];
            for (int i = 0; i < this._inputData.Length; i++)
            {
                this._inputData[i] = this._rnd.Next(-200, 200);
            }
        }


        private void btnMax_Click(object sender, EventArgs e)
        {
            try
            {
                DownSampleHelper.Max(this._inputData, this._outputData);
                ShowData(this._inputData, this._outputData);
                labelState.Text = "Max";
            }
            catch (Exception ex)
            {
                Loger.Error(ex);
            }
        }

        private void btnMin_Click(object sender, EventArgs e)
        {
            try
            {
                DownSampleHelper.Min(this._inputData, this._outputData);
                ShowData(this._inputData, this._outputData);
                labelState.Text = "Min";
            }
            catch (Exception ex)
            {
                Loger.Error(ex);
            }
        }

        private void btnMaxMin_Click(object sender, EventArgs e)
        {
            try
            {
                DownSampleHelper.MaxMin(this._inputData, this._outputData);
                ShowData(this._inputData, this._outputData);
                labelState.Text = "MaxMin";
            }
            catch (Exception ex)
            {
                Loger.Error(ex);
            }
        }

        private void btnAvg_Click(object sender, EventArgs e)
        {
            try
            {
                DownSampleHelper.Average(this._inputData, this._outputData);
                ShowData(this._inputData, this._outputData);
                labelState.Text = "Average";
            }
            catch (Exception ex)
            {
                Loger.Error(ex);
            }
        }

        private void btnMid_Click(object sender, EventArgs e)
        {
            try
            {
                DownSampleHelper.Middle(this._inputData, this._outputData);
                ShowData(this._inputData, this._outputData);
                labelState.Text = "Middle";
            }
            catch (Exception ex)
            {
                Loger.Error(ex);
            }
        }

        private void btnRnd_Click(object sender, EventArgs e)
        {
            try
            {
                DownSampleHelper.Random(this._inputData, this._outputData);
                ShowData(this._inputData, this._outputData);
                labelState.Text = "Random";
            }
            catch (Exception ex)
            {
                Loger.Error(ex);
            }
        }


    }
}
